package com.xiguaji.tiktok.v1.ins.blogger.service;

import com.xiguaji.tiktok.v1.ins.blogger.dto.*;
import com.xiguaji.tiktok.v1.ins.blogger.dto.es.InsBlogger;
import com.xiguaji.tiktok.v1.ins.blogger.dto.es.StatisticsData;
import com.xiguaji.tiktok.v1.ins.blogger.model.InsStBloggerFlBrandCategory;
import com.xiguaji.tiktok.v1.ins.blogger.repository.InsBloggerRepository;
import com.xiguaji.tiktok.v1.ins.blogger.repository.InsStBloggerFlBrandCategoryRepository;
import com.xiguaji.tiktok.v1.ins.comment.dto.InsActiveTime;
import com.xiguaji.tiktok.v1.ins.comment.repository.InsCommentRepository;
import com.xiguaji.tiktok.v1.ins.config.InsConfig;
import com.xiguaji.tiktok.v1.ins.dic.service.DicService;
import lombok.val;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;


/**
 * 粉丝相关服务
 * @author Huangxin
 */
@Service
public class InsBloggerFansService {

    /**
     * InsBloggerRepository
     */
    @Autowired
    InsBloggerRepository insBloggerRepository;

    /**
     * InsStBloggerFlBrandCategoryRepository
     */
    @Autowired
    InsStBloggerFlBrandCategoryRepository insStBloggerFlBrandCategoryRepository;

    /**
     * insCommentRepository
     */
    @Autowired
    InsCommentRepository insCommentRepository;

    /**
     * insBloggerService
     */
    @Autowired
    InsBloggerEsService insBloggerEsService;

    /**
     * insConfig
     */
    @Autowired
    InsConfig insConfig;

    /**
     *
     */
    @Autowired
    DicService dicService;

    /**
     *
     */
    public static final String FEMALE = "FEMALE";

    /**
     *
     */
    public static final BigDecimal PERCENT = new BigDecimal(100);

    /**
     *
     */
    Map<String,String> nationDic;

    /**
     *
     */
    Map<String,String> languageDic;

    /**
     *
     */
    @PostConstruct
    public void init(){
        nationDic = dicService.getDicNationMap();
        languageDic = dicService.getDicLanguageMap();
    }


    /**
     * 根据uid 粉丝质量分析信息
     * @param uid
     * @return
     */
    public InsBloggerFansGoalResponse getFansGoal(long uid){
        InsBloggerFansGoalResponse insBloggerFansGoalResponse;
        val fansGoal = insBloggerRepository.findFansQualityBaseInfoByUid(uid);
        if(fansGoal.isEmpty()){
            insBloggerFansGoalResponse = new InsBloggerFansGoalResponse();
        }else{
            insBloggerFansGoalResponse = fansGoal.get();
        }
        // 同分类同量级相关字段

        val opt = insBloggerRepository.findSaneCfsRealFollower(uid);
        if(opt.isPresent()){
            InsBloggerCfsData insBloggerCfsData = opt.get();
            if(insBloggerCfsData.getExceed() != null){
                insBloggerFansGoalResponse.setExceed(insBloggerCfsData.getExceed() >= 100 ? 99.9 : insBloggerCfsData.getExceed());
            }
            if(insBloggerCfsData.getSameCfsRate() != null){
                insBloggerFansGoalResponse.setSameSizeGrowRate(insBloggerCfsData.getSameCfsRate());
            }
            if(insBloggerCfsData.getRate() != null && insBloggerCfsData.getRate() == 0){
                insBloggerFansGoalResponse.setExceed(0.0);
            }
        }
        // 获取活跃小时、天
        insBloggerFansGoalResponse.setActiveDay(getMaxActiveDay(uid));
        insBloggerFansGoalResponse.setActiveHour(getMaxActiveHour(uid));

        return insBloggerFansGoalResponse;
    }

    /**
     * 根据uid 粉丝概况
     * @param uid
     * @return
     */
    public InsBloggerFansOverviewResponse getFansOverview(long uid){
        InsBloggerFansOverviewResponse insBloggerFansOverviewResponse = new InsBloggerFansOverviewResponse();
        InsBloggerFansOverview fan;
        // 粉丝关注的品牌
        List<InsBloggerSimple> brands = insBloggerRepository.findBrandByUid(uid,0,insConfig.getFanOverViewBrandCount());

        // 粉丝关注的品牌的行业分类
        List<InsStBloggerFlBrandCategory> category = insStBloggerFlBrandCategoryRepository.findBrandCategoryByUid(uid,2,0,insConfig.getFanOverViewCategoryCount());

        // 粉丝概况
        Optional<InsBloggerFansOverview> insBloggerFansOverview = insBloggerRepository.findFansOverviewByUid(uid);

        if(!brands.isEmpty()){
            insBloggerFansOverviewResponse.setBrand(brands);
        }
        if(!category.isEmpty()){
            insBloggerFansOverviewResponse.setCategory(category);
        }
        if(insBloggerFansOverview.isEmpty()){
            fan = new InsBloggerFansOverview();
        }else{
            fan = insBloggerFansOverview.get();
        }

        // 获取活跃小时、天
        fan.setActiveDay(getMaxActiveDay(uid));
        fan.setActiveHour(getMaxActiveHour(uid));

        insBloggerFansOverviewResponse.setFan(fan);
        return insBloggerFansOverviewResponse;
    }

    /**
     * 获取粉丝最活跃的周内天
     * @param uid
     * @return
     */
    public Integer getMaxActiveDay(long uid){
        List<InsActiveTime> activeTimes = insCommentRepository.findActiveDayByUid(uid);
        return getMaxActiveTime(activeTimes);
    }

    /**
     * 获取最活跃的小时
     * @param uid
     * @return
     */
    public Integer getMaxActiveHour(long uid){
        List<InsActiveTime> activeTimes = insCommentRepository.findActiveHourByUid(uid);
        return getMaxActiveTime(activeTimes);
    }

    /**
     * 获取最活跃的时间
     * @param activeTimes
     * @return
     */
    public Integer getMaxActiveTime(List<InsActiveTime> activeTimes){
        int time = 0;
        int maxCount = 0;
        if(activeTimes != null && !activeTimes.isEmpty()){
            for(InsActiveTime activeTime : activeTimes){
                if(activeTime != null && activeTime.getCount() != null && activeTime.getActiveTime() != null){
                    if(activeTime.getCount() > maxCount){
                        maxCount = activeTime.getCount();
                        time = activeTime.getActiveTime();
                    }

                }
            }
            return time;
        } else {
            return null;
        }
    }

    /**
     * 根据uid 粉丝画像
     * @param uid
     * @return
     */
    public InsBloggerFansPortraitResponse getFansPortrait(long uid){
        // todo 后面可能会把数据缓存在 redis 里
        InsBloggerFansPortraitResponse insBloggerFansPortraitResponse = new InsBloggerFansPortraitResponse();
        // 活跃时间
        setActiveTime(uid,insBloggerFansPortraitResponse);

        // 设置年龄段
        setGeneration(uid,insBloggerFansPortraitResponse);
        // 设置成人占比（因为年龄段从数据库走所以成人占比也得走数据库）
        setAdultRate(uid,insBloggerFansPortraitResponse);

        // 收入占比
        setIncome(uid,insBloggerFansPortraitResponse);

        // 从es中查询数据
        InsBlogger insBlogger = insBloggerEsService.getInsBloggerFromEsByUid(uid);
        if(insBlogger != null){
            // 语言
            setLanguage(insBlogger,insBloggerFansPortraitResponse);

            // 人种
            setRace(insBlogger,insBloggerFansPortraitResponse);

            // 国家
            setNation(insBlogger,insBloggerFansPortraitResponse);

            // 性别
            setGender(insBlogger,insBloggerFansPortraitResponse);

            // 账户类型
            setAccountType(insBlogger,insBloggerFansPortraitResponse);
        }
        return insBloggerFansPortraitResponse;
    }

    /**
     * 设置活跃时间
     * @param uid
     * @param insBloggerFansPortraitResponse
     */
    public void setActiveTime(long uid,InsBloggerFansPortraitResponse insBloggerFansPortraitResponse){
        double[] activeHour = new double[24];
        double[] activeDay = new double[7];
        List<InsActiveTime> activeDays = insCommentRepository.findActiveDayByUid(uid);
        List<InsActiveTime> activeHours = insCommentRepository.findActiveHourByUid(uid);
        getActiveTime(activeDays,activeDay);
        getActiveTime(activeHours,activeHour);
        insBloggerFansPortraitResponse.setActiveDay(activeDay);
        insBloggerFansPortraitResponse.setActiveHour(activeHour);
    }

    /**
     * 设置成人占比
     * @param uid
     * @param insBloggerFansPortraitResponse
     */
    public void setAdultRate(long uid,InsBloggerFansPortraitResponse insBloggerFansPortraitResponse){
        Optional<InsBloggerFansGenderAdult> insBloggerFansGenderAdult = insBloggerRepository.findFansGenderByUid(uid);
        if(insBloggerFansGenderAdult.isEmpty()){
            insBloggerFansPortraitResponse.setAdult(null);
        }else{
            InsBloggerFansGenderAdult fansGenderAdult = insBloggerFansGenderAdult.get();
            insBloggerFansPortraitResponse.setAdult(fansGenderAdult.getAdultRate());
        }
    }

    /**
     * 设置年龄段
     * @param uid
     * @param insBloggerFansPortraitResponse
     */
    public void setGeneration(long uid,InsBloggerFansPortraitResponse insBloggerFansPortraitResponse){
        // 年龄段 (es没存走数据库)
        List<InsBloggerFansGeneration> insBloggerFansGeneration = insBloggerRepository.findFansGenerationByUid(uid);
        if(insBloggerFansGeneration != null && !insBloggerFansGeneration.isEmpty()){
            insBloggerFansPortraitResponse.setGeneration(insBloggerFansGeneration);
            for(InsBloggerFansGeneration fansGeneration : insBloggerFansGeneration){
                if(fansGeneration != null && fansGeneration.getGenerationRank() == 1){
                    insBloggerFansPortraitResponse.setGenerationTop(fansGeneration.getGeneration());
                    insBloggerFansPortraitResponse.setGenerationRateTop(fansGeneration.getGenerationRate());
                }
            }
        }
    }

    /**
     * 设置收入
     * @param uid
     * @param insBloggerFansPortraitResponse
     */
    public void setIncome(long uid,InsBloggerFansPortraitResponse insBloggerFansPortraitResponse){
        List<InsBloggerFansIncome> insBloggerFansIncomes = insBloggerRepository.findFansIncomeByUid(uid);
        if(insBloggerFansIncomes != null && !insBloggerFansIncomes.isEmpty()){
            insBloggerFansPortraitResponse.setIncome(insBloggerFansIncomes);
        }
    }

    /**
     * 设置账户类型
     * @param insBlogger
     * @param insBloggerFansPortraitResponse
     */
    public void setAccountType(InsBlogger insBlogger,InsBloggerFansPortraitResponse insBloggerFansPortraitResponse){
        // 设置粉丝账户类型
        insBloggerFansPortraitResponse.setRealFollowerRate(getPercent(insBlogger.getRealFollowerRate()));
        insBloggerFansPortraitResponse.setMassiveFollowingRate(getPercent(insBlogger.getMassiveFollowingRate()));
        insBloggerFansPortraitResponse.setSuspiciousRate(getPercent(insBlogger.getSuspiciousRate()));

    }

    /**
     * 设置国家
     * @param insBlogger
     * @param insBloggerFansPortraitResponse
     */
    public void setNation(InsBlogger insBlogger,InsBloggerFansPortraitResponse insBloggerFansPortraitResponse){
        List<StatisticsData<Double>> nationDistribution = insBlogger.getNationDistribution();
        if(nationDistribution != null && !nationDistribution.isEmpty()){
            List<InsBloggerFansNation> insBloggerFansNations = new ArrayList<>(insConfig.getFansPortraitNationCount());
            for(StatisticsData<Double> nation : nationDistribution){
                if(insBloggerFansNations.size() >= insConfig.getFansPortraitNationCount()){
                    break;
                }
                if(nation != null){
                    InsBloggerFansNation insBloggerFansNation = new InsBloggerFansNation();
                    insBloggerFansNation.setNationName(nationDic.get(nation.getProperty()));
                    insBloggerFansNation.setNationRate(getPercent(nation.getValue()));
                    insBloggerFansNations.add(insBloggerFansNation);
                }
            }
            insBloggerFansPortraitResponse.setNation(insBloggerFansNations);
        }
    }

    /**
     *
     * @param value
     * @return
     */
    public Double getPercent(Double value){
        if(value == null){
            return null;
        }
        return new BigDecimal(value.toString()).multiply(PERCENT).doubleValue();
    }

    /**
     * 设置语言
     * @param insBlogger
     * @param insBloggerFansPortraitResponse
     */
    public void setLanguage(InsBlogger insBlogger,InsBloggerFansPortraitResponse insBloggerFansPortraitResponse){
        List<StatisticsData<Double>> languageDistribution = insBlogger.getLanguageDistribution();
        if(languageDistribution != null && !languageDistribution.isEmpty()){
            List<InsBloggerFansLanguage> insBloggerFansLanguages = new ArrayList<>(insConfig.getFansPortraitLanguageCount());
            for(StatisticsData<Double> language : languageDistribution){
                if(insBloggerFansLanguages.size() >= insConfig.getFansPortraitLanguageCount()){
                    break;
                }
                if(language != null){
                    InsBloggerFansLanguage insBloggerFansLanguage = new InsBloggerFansLanguage();
                    insBloggerFansLanguage.setLanguageName(languageDic.get(language.getProperty()));
                    insBloggerFansLanguage.setLanguageRate(getPercent(language.getValue()));
                    insBloggerFansLanguages.add(insBloggerFansLanguage);
                }
            }
            insBloggerFansPortraitResponse.setLanguage(insBloggerFansLanguages);
        }
    }

    /**
     * 设置人种
     * @param insBlogger
     * @param insBloggerFansPortraitResponse
     */
    public void setRace(InsBlogger insBlogger,InsBloggerFansPortraitResponse insBloggerFansPortraitResponse){
        List<StatisticsData<Double>> raceDistribution = insBlogger.getRaceDistribution();
        if(raceDistribution != null && !raceDistribution.isEmpty()){
            List<InsBloggerFansRace> insBloggerFansRaces = new ArrayList<>(insConfig.getFansPortraitRaceCount());
            for(StatisticsData<Double> race : raceDistribution){
                if(race != null){
                    InsBloggerFansRace insBloggerFansRace = new InsBloggerFansRace();
                    insBloggerFansRace.setRaceName(race.getProperty());
                    insBloggerFansRace.setRaceRate(getPercent(race.getValue()));
                    insBloggerFansRaces.add(insBloggerFansRace);
                }
            }
            insBloggerFansPortraitResponse.setRace(insBloggerFansRaces);
        }
    }

    /**
     * 设置性别
     * @param insBlogger
     * @param insBloggerFansPortraitResponse
     */
    public void setGender(InsBlogger insBlogger,InsBloggerFansPortraitResponse insBloggerFansPortraitResponse){
        List<StatisticsData<Double>> genderDistribution = insBlogger.getGenderDistribution();
        if(genderDistribution != null && !genderDistribution.isEmpty()){
            for (StatisticsData<Double> statisticsData : genderDistribution){
                if(statisticsData != null){
                    if(FEMALE.equals(statisticsData.getProperty())){
                        insBloggerFansPortraitResponse.setFemaleRate(getPercent(statisticsData.getValue()));
                    }else{
                        insBloggerFansPortraitResponse.setMaleRate(getPercent(statisticsData.getValue()));
                    }
                }
            }
        }
    }

    /**
     * 活跃时间设置
     * @param activeTimes
     * @param active
     */
    public void getActiveTime(List<InsActiveTime> activeTimes,double[] active){
        if(!activeTimes.isEmpty()){
            int sum = 0;
            for(InsActiveTime activeTime : activeTimes){
                if(activeTime != null && activeTime.getCount() != null
                        && activeTime.getActiveTime() != null
                        && activeTime.getActiveTime() < active.length){
                    sum += activeTime.getCount();
                }
            }
            if(sum > 0){
                for(InsActiveTime activeTime : activeTimes){
                    if(activeTime != null && activeTime.getCount() != null
                            && activeTime.getActiveTime() != null
                            && activeTime.getActiveTime() < active.length){
                        active[activeTime.getActiveTime()] = (double)((long)activeTime.getCount() * 10000 / sum) / 100;
                    }
                }
            }

        }
    }


    /**
     * 根据uid 获取粉丝品牌亲和力Top20
     * @param uid
     * @return
     */
    public List<InsBloggerSimple> getFansBrand(long uid,int page){
        page = page > 0 ? page : 1;
        int start = (page - 1) * insConfig.getFansPortraitBrandPageSize();
        List<InsBloggerSimple> insBloggerSimples = insBloggerRepository.findBrandByUid(uid,start,insConfig.getFansPortraitBrandPageSize());
        return insBloggerSimples;
    }

    /**
     * 根据uid 粉丝品牌兴趣分布
     * @param uid
     * @return
     */
    public List<InsStBloggerFlBrandCategory> getFansBrandCategory(long uid){
        // 粉丝关注的品牌的行业分类
        List<InsStBloggerFlBrandCategory> category = insStBloggerFlBrandCategoryRepository.findBrandCategoryByUid(uid,1,0,insConfig.getFansPortraitCategoryCount());
        return category;
    }

    /**
     * 根据uid 粉丝兴趣分布
     * @param uid
     * @return
     */
    public List<InsStBloggerFlBrandCategory> getFansCategory(long uid){
        // 粉丝关注的品牌的行业分类
        List<InsStBloggerFlBrandCategory> category = insStBloggerFlBrandCategoryRepository.findBrandCategoryByUid(uid,2,0,insConfig.getFansPortraitCategoryCount());
        return category;
    }
}
